﻿#region

using System;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

#endregion

namespace Pob.GameObjects
{
    public enum DrawStringMode
    {
        Minimal, 

        WithSelected, 

        Extended
    }

    public enum OringeMode
    {
        TopLeft, 

        MiddleLeft, 

        BottomLeft, 

        TopCenter, 

        MiddleCenter, 

        BottomCenter, 

        TopRight, 

        MiddleRight, 

        BottomRight, 
    }

    public class DrawString : DrawableGameComponent, ICloneable
    {
        #region Fields

        private readonly string _asset;

        private readonly float _layerDepth;

        private readonly OringeMode _originMode;

        private readonly float _rotation;

        private readonly SpriteEffects _spriteEffects;

        private bool _animationMode;

        private Color _color;

        private DrawStringMode _drawMode;

        private SpriteFont _font;

        private Vector2 _measuredString;

        private Vector2 _position;

        private float _scale;

        private bool _selected;

        private SpriteBatch _spriteBatch;

        private string _text;

        #endregion

        #region Constructors and Destructors

        public DrawString(Game game, string asset, string text, Vector2 position, Color color)
            : base(game)
        {
            _text = text;
            _asset = asset;
            _position = position;
            _color = color;
            _drawMode = DrawStringMode.Minimal;
        }

        public DrawString(Game game, string asset, string text, Vector2 position, Color color, float rotation = 0f, float scale = 1f, SpriteEffects spriteEffects = SpriteEffects.None, float layerDepth = 0f, bool selected = false, DrawStringMode drawStringMode = DrawStringMode.Extended, OringeMode originMode = OringeMode.MiddleCenter)
            : base(game)
        {
            _text = text;
            _asset = asset;
            _position = position;
            _color = color;
            _rotation = rotation;
            _scale = scale;
            _spriteEffects = spriteEffects;
            _layerDepth = layerDepth;
            _selected = selected;
            _originMode = originMode;
            _drawMode = drawStringMode;
        }

        #endregion

        #region Public Properties

        public DrawStringMode DrawMode
        {
            set
            {
                _drawMode = value;
            }
        }

        public Vector2 Position
        {
            set
            {
                _position = value;
            }
        }

        public float Scale
        {
            set
            {
                _scale = value;
            }
        }

        public bool Selected
        {
            get
            {
                return _selected;
            }

            set
            {
                _selected = value;
                if (!_selected)
                {
                    _scale = 1;
                }
            }
        }

        public string Text
        {
            get
            {
                return _text;
            }

            set
            {
                _text = value;
                _measuredString = _font.MeasureString(_text);
            }
        }

        public float Width
        {
            get
            {
                return _measuredString.X;
            }
        }

        #endregion

        #region Public Methods and Operators

        public object Clone()
        {
            var drawString = new DrawString(Game, _asset, _text, _position, _color, _rotation, _scale, _spriteEffects, _layerDepth, _selected, _drawMode, _originMode);
            return drawString;
        }

        public override void Draw(GameTime gameTime)
        {
            _spriteBatch.Begin();

            switch (_drawMode)
            {
                case DrawStringMode.Minimal:
                    {
                        _spriteBatch.DrawString(_font, _text, _position, _color);
                        break;
                    }

                case DrawStringMode.WithSelected:
                    {
                        _spriteBatch.DrawString(_font, _text, _position, _color, _rotation, GetOrigin(), _scale, _spriteEffects, _layerDepth);
                        break;
                    }

                case DrawStringMode.Extended:
                    {
                        _spriteBatch.DrawString(_font, _text, _position, _color, _rotation, GetOrigin(), _scale, _spriteEffects, _layerDepth);
                        break;
                    }
            }

            _spriteBatch.End();
        }

        public override void Update(GameTime gameTime)
        {
            if (_drawMode == DrawStringMode.WithSelected && _selected)
            {
                if (_scale > 1.3)
                {
                    _animationMode = true;
                }

                if (_scale < 1)
                {
                    _animationMode = false;
                }

                StringSelectedAnimation(_animationMode);
            }

            _color = _selected ? Color.Orange : Color.White;

            base.Update(gameTime);
        }

        #endregion

        #region Methods

        protected override void LoadContent()
        {
            _spriteBatch = new SpriteBatch(GraphicsDevice);
            _font = Game.Content.Load<SpriteFont>(_asset);
            _measuredString = _font.MeasureString(_text);
        }

        private Vector2 GetOrigin()
        {
            var origin = new Vector2(0, 0);
            switch (_originMode)
            {
                case OringeMode.TopLeft:
                    {
                        origin = new Vector2(0, 0);
                        break;
                    }

                case OringeMode.MiddleLeft:
                    {
                        origin = new Vector2(0, _measuredString.Y / 2);
                        break;
                    }

                case OringeMode.BottomLeft:
                    {
                        origin = new Vector2(0, _measuredString.Y);
                        break;
                    }

                case OringeMode.TopCenter:
                    {
                        origin = new Vector2(_measuredString.X / 2, 0);
                        break;
                    }

                case OringeMode.MiddleCenter:
                    {
                        origin = new Vector2(_measuredString.X / 2, _measuredString.Y / 2);
                        break;
                    }

                case OringeMode.BottomCenter:
                    {
                        origin = new Vector2(_measuredString.X / 2, _measuredString.Y);
                        break;
                    }

                case OringeMode.TopRight:
                    {
                        origin = new Vector2(_measuredString.X, 0);
                        break;
                    }

                case OringeMode.MiddleRight:
                    {
                        origin = new Vector2(_measuredString.X, _measuredString.Y / 2);
                        break;
                    }

                case OringeMode.BottomRight:
                    {
                        origin = new Vector2(_measuredString.X, _measuredString.Y);
                        break;
                    }
            }

            return origin;
        }

        private void StringSelectedAnimation(bool animationMode)
        {
            if (animationMode)
            {
                _scale = _scale - 0.01f;
            }
            else
            {
                _scale = _scale + 0.01f;
            }
        }

        #endregion
    }
}